<?php

namespace App\Service\Pay;

use App\Models\Bank;
use App\Models\Card;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Exception;
use Illuminate\Support\Facades\Log;

class BPayService extends PayService implements Pay
{

    /**
     * 充值通知地址
     * @var string
     */
    protected string $pay_notify_url = '/api/v1/b_recharge';

    /**
     * 代付通知地址
     * @var string
     */
    protected string $withdrawal_notify_url = '/api/v1/b_withdrawal';


    //充值
    public function recharge($attach = [])
    {
        try {
            $this->setReturnUrl();
            $param = [
                'merchantNo' => $this->merchant,
                'merchantOrderNo' => $this->order->no,
                'countryCode' => 'VNM',
                'currencyCode' => 'VND',
                'paymentType' => $this->pay_code,
                'paymentAmount' => sprintf('%.2f', $this->order->amount),
                'goods' => 'recharge',
                'pageUrl' => $this->return_url,
                'notifyUrl' => url($this->pay_notify_url),
            ];
            $param['sign'] = $this->sign($param, $this->private_key);
            $response = Http::asJson()->post($this->pay_url, $param);
            $result = json_decode($response->body(), true);
            $this->order->param = json_encode($param, JSON_UNESCAPED_UNICODE);
            $this->order->response = json_encode($result, JSON_UNESCAPED_UNICODE);
            Log::info('bpay充值', ['result'=>$result]);
            if (isset($result['code']) && $result['code'] == 200) {
                $this->order->payment_no = $result['data']['orderNo'];
                $this->order->save();
                return $result['data']['paymentUrl'];
            }
            $this->rechargeFail();
            return false;
        } catch (Exception $exception) {
            $error_message = json_encode(['msg' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()], JSON_UNESCAPED_UNICODE);
            $this->rechargeFail($error_message);
            return false;
        }
    }

    public function withdrawal($attach = [])
    {
        info('提现订单开始:'.$this->order->no);
        try {
            //$card = json_decode($this->order->card, true);
            $card = Card::query()->where('user_id', '=', $this->order->user_id)->first();
            $bank_code = '';
            $bankname = '';
            if($card['bank_id'] != 0){
                $bank = Bank::getBank($card['bank_id']);
                $bank_code = $bank['b_code'];
                $bankname = $bank['name'];
            }
            $param = [
                'merchantNo' => $this->merchant,
                'merchantOrderNo'=> $this->order->no,
                'countryCode' => 'VNM',
                'currencyCode' => 'VND',
                'transferType' => '902810205001',
                'transferAmount' => sprintf('%.2f', $this->order->actual_amount),
                'feeDeduction' => 1,
                'remark' => 'transferremark',
                'notifyUrl' => url($this->withdrawal_notify_url),
                'extendedParams' => "bankAccount^".$card->number."|bankCode^".$bank_code."|payeeName^".$card->username
            ];
            $param['sign'] = $this->sign($param, $this->private_key);

            $response = Http::asJson()->post($this->withdrawal_url, $param);
            info('提现订单响应:'.$response);
            $result = json_decode($response->body(), true);
            $result = is_array($result) ? $result : [];
            //记录入参跟响应
            $state = isset($result['code']) && $result['code'] == 200;
            $this->withdrawalCallback($param, $result, $result['data']['orderNo'] ?? '', $state);
            $this->order->save();
        } catch (Exception $exception) {
            $this->withdrawalCallback([], ['msg' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()], '', false);
        }
    }


    /**
     * 签名
     * @param $data
     * @param $secret
     * @return string
     */
    protected function sign($data, $secret): string
    {
        ksort($data);
        $str = '';
        foreach ($data as $key => $val) {
//            if ($val != null) {
            $str .= $key . '=' . $val . '&';
//            }
        }
        $str = rtrim($str, '&');
        $merchant_private_key = '-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMWmu2CXZn/ZSQWBZ6aVH0k4jnLPG1c/Bfs/JYzldi7kqkFmWBsqPVdH+lEmcTU3UvZcbJZPa8kz+IOHFJIAfMcgdQelQhM7JFDnObfLfuFkQFTIZaxEMpWbOxJmOQbkboWaFGvLMODZP9tK5edkk4Y0CjNtLCWJZAd2eLEomfxrAgMBAAECgYAK/WZVzJVKbo582+Ejhg8jRx3EjHd8tmhiu/QejXOwz84XrNUhTYvzmnD0qiqJRvY59JGlGe1oVpdu2MfwBk7pum3448jl/l/y8RNdGX0vEerIPHbnvodjHgfijiBngErrseja5Tszy3CsTDng2AVgxtdiIX85eMMGyi864y0ooQJBAPSa14x7S4UHdxhEP9mILpP+NfR8CqU0uIBRQDQNlpmrUnDiUHYsEDISjVroJFa5M/QrRCxHQ8npYuwjMP1iJtUCQQDO2+v4DcAs1+kxJn4RRr89uNYZYeOOwQzG9iTz28xqEMJq6dSm7SNdhP94+KDrIew6PUkdZEBzAmbqBDan+7Y/AkAqfCaKMPQaBATsgxYv+1ZTwCiw8UaMEU8mgnZLVDzfLgGgt75P+DFL8Sr6Ki39nidm9ojdw/cDP/U9nJMqv3yNAkAn1VmfLqau+/S/rjXghcsVy54OzTbQqoQXXBbJjq3STt/hTp3QdyG0RIQde2MhZCrlHCAUNNXkT7YZoi4UMvhpAkEA8zuBaWnkpOLTSGdb2mwgAN2XrDqMNBDyhp66YSYp7JDwiGLTvA9ztUDOyVoI+qrosoSqv0ogrDhj0fVyfOv7RQ==
-----END PRIVATE KEY-----';
        $merchant_private_key = openssl_get_privatekey($merchant_private_key);
        openssl_sign($str, $sign_info, $merchant_private_key, OPENSSL_ALGO_MD5);
        $sign = base64_encode($sign_info);
        return $sign;
    }

    /**
     * 验签
     * @param array $params
     * @param string $type
     * @return bool
     */
    public function checkSign(array $params, string $type): bool
    {
        $sign = $params['sign'];
        // 验证签名参数是否正确
        unset($params['sign']);

        $pay_public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSesEfow0G3D7Cn/7YH+k9ZYgdJZe04m+Hi8erzxZS6NhzbcZlvRmSZKlKNX6/DOCUlZPirq26FQnl7tUYH1BeQepVBcYo4qiQrMoULXujJuyTtmIqNgyz9E+wgDT9Esrq1BmX6wEQsCdcNwry5WYS40AU6dAOflo6CGJJWN3l4wIDAQAB
-----END PUBLIC KEY-----';

        ksort($params);
        $str = '';
        foreach ($params as $key => $val) {
//            if ($val != null) {
            $str .= $key . '=' . $val . '&';
//            }
        }
        $str = rtrim($str, '&');

        $pay_public_key = openssl_get_publickey($pay_public_key);
        $flag = openssl_verify($str,base64_decode($sign),$pay_public_key,OPENSSL_ALGO_MD5);
        if ($flag) {
            return true;
        } else {
            return false;
        }
    }

}
